﻿using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;


namespace XFABManager
{

    public class DownloadObjectInfo {

        public string url;
        public string localfile;
        public long length;

        public DownloadObjectInfo(string url,string localfile,long length=0) {
            this.url = url;
            this.localfile = localfile;
            this.length = length;
        }

    }

    /// <summary>
    /// 下载多个文件的请求 
    /// 用来替换 DownloadManager
    /// </summary>
    public class DownloadFilesRequest : CustomAsyncOperation<DownloadFilesRequest>
    {

        //private Dictionary<string, string> files = new Dictionary<string, string>();

        private Queue<DownloadObjectInfo> downloadObjects = null;

        // 已经下载完成的文件
        private List<DownloadObjectInfo> downloadedObjects = new List<DownloadObjectInfo>();

        public long Speed { get; private set; }


        /// <summary>
        /// 已经下载的文件大小
        /// </summary>
        public long DownloadedSize { 
            get {
                all_download_size = 0;
                foreach (var item in downloadedObjects)
                {
                    all_download_size += item.length;
                }

                foreach (var item in downloadFiles)
                {
                    all_download_size += item.DownloadedSize;
                }
                 
                return all_download_size;
            } 
        }

        //private long cur_download_size; // 当前正在下载的这个文件 已下载的大小

        private long all_download_size;
        // 当某个文件下载完成时触发
        public System.Action<DownloadObjectInfo> onFileDownloadCompleted;

        public DownloadFilesRequest(List<DownloadObjectInfo> downloadObjects)
        {

            AllSize = 0;

            this.downloadObjects = new Queue<DownloadObjectInfo>();
            foreach (var item in downloadObjects)
            {
                this.downloadObjects.Enqueue(item);
                AllSize += item.length;
            }
            //this.downloadObjects = downloadObjects;
        }


        /// <summary>
        /// 所有需要下载的文件总大小
        /// </summary>
        public long AllSize { get; private set; }

        #region 文件下载
        
        private const int  min_download_count = 10;
        private const int max_download_count = 30;

        private int current_download_count = min_download_count;

        private List<DownloadFileRequest> downloadFiles = new List<DownloadFileRequest>();


        private Dictionary<int, long> download_speeds = new Dictionary<int, long>();

        private const int caculate_speed_frame_count = 30; // 计算下载速度需要的帧数

        private long caculate_temp_speed = 0;         // 临时存放速度
        private long caculate_speed_count = 0;         // 临时存放速度
        #endregion




        //public IEnumerator Download()
        //{ 
        //    if (downloadObjects == null || downloadObjects.Count == 0)
        //    {
        //        Debug.LogWarning("需要下载的文件为空,请添加后重试!");
        //        Completed();
        //        yield break;
        //    }

        //    downloadedObjects.Clear();

        //    int index = 0;
        //    foreach (var info in downloadObjects)
        //    {

        //        //string file_url = key;
        //        string localfile = info.localfile ;

        //        if (string.IsNullOrEmpty(info.url) || string.IsNullOrEmpty(localfile)) { continue; }
        //        DownloadFileRequest download = DownloadFileRequest.Download(info.url, localfile,info.length);

        //        while (!download.isDone)
        //        {
        //            yield return null;
        //            progress =  (DownloadedSize / 1000000000.0f) / (AllSize/ 1000000000.0f);
        //            Speed = download.Speed;
        //            cur_download_size = download.DownloadedSize;
        //            //CurrentSpeedFormatStr = downloadTool.CurrentSpeedFormatStr;
        //        }

        //        if (!string.IsNullOrEmpty(download.error))
        //        {
        //            error = string.Format("下载文件失败:{0} url:{1}", download.error, info.url);
        //            Completed();
        //            yield break;
        //        }

        //        // 

        //        downloadedObjects.Add(info);
        //        cur_download_size = 0;
        //        index++;
        //        onFileDownloadCompleted?.Invoke(info);
        //    }
        //    Completed();
        //}

        public IEnumerator Download()
        {
            if (downloadObjects == null || downloadObjects.Count == 0)
            {
                Debug.LogWarning("需要下载的文件为空,请添加后重试!");
                Completed();
                yield break;
            }

            downloadedObjects.Clear();

            int speedTimer = 0;

            while (downloadObjects.Count > 0 || IsDownloading())
            {

                yield return null;

                // 可以下载
                while (IsCanDownload())
                {
                    DownloadObjectInfo info = downloadObjects.Dequeue();
                    if (string.IsNullOrEmpty(info.url) || string.IsNullOrEmpty(info.localfile)) continue;
                    DownloadFileRequest download = DownloadFileRequest.Download(info.url, info.localfile, info.length);
                    download.completed += (request) =>
                    {
                        if (string.IsNullOrEmpty(download.error))
                        {
                            // 文件下载完成
                            downloadedObjects.Add(info);
                            onFileDownloadCompleted?.Invoke(info);
                            downloadFiles.Remove(request);
                        }
                    };
                    downloadFiles.Add(download);
                }

                progress = (DownloadedSize / 1000000000.0f) / (AllSize / 1000000000.0f);

                if (DownloadSpeed() != 0)
                { // 如果速度不等于 0 直接赋值
                    Speed = DownloadSpeed();
                    speedTimer = 0;
                }
                else
                {   // 如果速度等于 0 等60帧之后再赋值
                    speedTimer++;
                    if (speedTimer > 60)
                    {
                        Speed = 0;
                    }
                }

                // 检查是否需要增加下载数量(自动调整同时下载的文件数量)
                CheckIsNeedIncreaseDownloadCount();


                if (IsDownloadAllError()) // 如果正在下载中的文件全都下载出错了 跳出循环
                    break;

            }
            
            // 检测文件是否下载出错
            if (IsDownloadError())
            {
                Completed(DownloadErrorMessage());
                yield break;
            }

            Completed();
        }



        // 判断是否能够下载
        private bool IsCanDownload()
        {

            if (downloadObjects.Count == 0) return false; // 没有需要下载的文件 所以不能下载

            // 判断正在下载中的文件有没有报错的
            foreach (var item in downloadFiles)
                if (item.isDone && !string.IsNullOrEmpty(item.error)) return false;

            // 判断数量
            if (downloadFiles.Count < current_download_count) return true;

            return false;
        }

        // 判断是否下载出错
        private bool IsDownloadError() {

            if (downloadFiles.Count == 0) return false;

       
            foreach (var item in downloadFiles)
                if (item.isDone && !string.IsNullOrEmpty(item.error)) return true;
             
            return false;
        }

        // 判断下载中的文件是不是都出错了
        private bool IsDownloadAllError() {
            if (downloadFiles.Count == 0) return false;

            foreach (var item in downloadFiles)
                if (!item.isDone || string.IsNullOrEmpty(item.error)) return false;

            return true;
        }

        // 判断是不是正在下载中
        private bool IsDownloading() {
            if (downloadFiles.Count == 0) return false;
            foreach (var item in downloadFiles)
                if (!item.isDone) return true;
            return false;
        }

        // 下载出错的信息
        private string DownloadErrorMessage() {

            StringBuilder stringBuilder = new StringBuilder();
            foreach (var item in downloadFiles)
                if (item.isDone && !string.IsNullOrEmpty(item.error)) 
                    stringBuilder.Append("文件:").Append(item.Url).Append("error:").Append(item.error).Append("\n");
                
            return stringBuilder.ToString();
        }
         
        // 当前下载的速度
        private long DownloadSpeed() {
            long speed = 0; 
            foreach (var item in downloadFiles) {
                if ( !item.isDone ) {
                    speed += item.Speed; 
                }
            } 
            return speed;
        }


        // 检查是否需要增加下载数量
        private void CheckIsNeedIncreaseDownloadCount() {

            if (!download_speeds.ContainsKey(current_download_count)) {
                // 计算中...
                caculate_speed_count++;
                caculate_temp_speed += DownloadSpeed();
                if (caculate_speed_count >= caculate_speed_frame_count) {
                    // 计算完毕
                    download_speeds.Add(current_download_count, caculate_temp_speed);
                    caculate_temp_speed = 0;
                    caculate_speed_count = 0;
                    //Debug.LogFormat("完成速度计算:{0} - {1}", current_download_count, download_speeds[current_download_count]); 
                    // 与上一个速度做对比
                    if (download_speeds.ContainsKey(current_download_count - 1))
                    {
                        if (download_speeds[current_download_count] - download_speeds[current_download_count - 1] > 100000)
                        {
                            // 继续增加
                            //Debug.LogFormat("速度明显提升 继续增加数量:{0} 当前速度:{1} 上次速度:{2}", current_download_count, download_speeds[current_download_count], download_speeds[current_download_count - 1]);

                            if (current_download_count<max_download_count)
                                current_download_count++;
                        }
                        //else {
                        //    Debug.LogFormat("速度未明显提升 停止增加数量:{0} 当前速度:{1} 上次速度:{2}", current_download_count, download_speeds[current_download_count], download_speeds[current_download_count - 1]);
                        //}
                    }
                    else {
                        // 自己是第一个没有上一个
                        current_download_count++;
                        //Debug.LogFormat("首次计算 增加数量:{0}", current_download_count);
                    }
                }
            }
        }


        [System.Obsolete("该方法已经过时,请使用DownloadFilesRequest.DownloadFiles(List<DownloadObjectInfo> files) 代替!",true)]
        public static DownloadFilesRequest DownloadFiles(Dictionary<string,string> files)
        {
            //DownloadFilesRequest downloadFiles = new DownloadFilesRequest(null);
            ////downloadFiles.AddRange(files);
            //CoroutineStarter.Start(downloadFiles.Download());
            return null;
        }

        public static DownloadFilesRequest DownloadFiles(List<DownloadObjectInfo> files)
        {
            DownloadFilesRequest downloadFiles = new DownloadFilesRequest(files);
            CoroutineStarter.Start(downloadFiles.Download());
            return downloadFiles;
        }

    }

}

